3章 変数、定数、リテラル、データ型
https://gyazo.com/51ba590422cb6160a4960060509a9941
変数と定数
var
varは非推奨。
let
let: 変数(variable)の宣言(declaration)と初期値の代入
let currentTempC = 16;
宣言は一度しか出来ない=再代入するときはletはつけない
currentTempC = 22.5;
初期値は必須ではない。undefinedになる。
let targetTempC; // undefined
let targetTempC = undefined; // ↑と同じ
ひとつのletで複数の変数を宣言可能
let targetTempC, room1 = "会議室A", room2 = "ロビー"; // targetTempC は undefined
const
const: 定数(constant)の宣言
const ROOM_TEMP_C = 26.5, MAX_TEMP_C = 36;
定数、グローバル変数など具体的な数値や文字はアッパーケース推奨。
変数か定数か
定数が使えるのであれば変数ではなく定数を使う。
識別子
識別子(identifier): 変数名や定数名として使われる文字列
ES2015の識別子の規則
1文字目: Unicode文字(数字や一部のUnicode文字を除く)、$, _,でなければならない
2文字目以降: Unicode文字(一部除く), 数字, $, _を使える。
予約語は識別子として使えない
識別子の表記に明確な慣習はないが…
スネークケースよりもキャメルケースが一般的
変数の識別子は大文字で始めない
_もしくは__で始まる識別子は特別な変数または内部変数を表す目的で使われる事が多いので、そうでない場合は名前の先頭につけるのは避ける
リテラル
リテラル(literal): プログラムで値を直接指定するものを表す。
code:javascript
let room1 = "会議室A"; // "会議室A"はリテラル(文字リテラル)
console.log(room1); // 会議室A
let currentRoom = room1;
console.log(currentRoom); // 会議室A
let nextRoom = 会議室A; // 会議室Aは引用符で囲まれていないのでリテラルでも変数でも定数でもない。
// ReferenceError: 会議室A is not defined
プリミティブ型とオブジェクト
JavaScriptでは値→プリミティブ(primitive)か オブジェクト(object)
プリミティブ: immutable
プリミティブを表すデータ型
Number
String
Boolean
null
undefined
Symbol
mutableなオブジェクト
Array
Date
RegExp
Map, WeakMap
Set, WeakSet
数値
多くの数値は近似値で表される
IEEE 754-2008という倍精度浮動小数点数の表現(64ビット)を使って実数値を近似する
console.log( 0.1 + 0.2 ); // 0.30000000000000004
JavaScriptには浮動小数点数型を持たない。
JavaScriptで認識される数値リテラル
10進数
整数
小数
scientific notation
2進数
8進数
16進数
数値リテラルではないが計算結果の値となることがあるもの
Infinity
-Infinity
NaN
Numberオブジェクトには重要な数値を表すプロパティが用意されている
code:javascript
const small = Number.EPSILON; /* 1と、1より大きい最小の値の差 */
console.log(small); // 2.220446049250313e-16
const bigInt = Number.MAX_SAFE_INTEGER; /* 表現できる最大の整数 */
console.log(bigInt); // 9007199254740991
const max = Number.MAX_VALUE; /* 表現できる最大の数値 */
console.log(max); // 1.7976931348623157e+308
const minInt = Number.MIN_SAFE_INTEGER; /* 表現できる最小の整数 */
console.log(minInt); // -9007199254740991
const min = Number.MIN_VALUE; /* 表現できる最小の数値 */
console.log(min); // 5e-324
const nInf = Number.NEGATIVE_INFINITY;
console.log(nInf); // -Infinity
const nan = Number.NaN;
console.log(nan); // NaN
const inf = Number.POSITIVE_INFINITY;
console.log(inf); // Infinity
文字列
文字列の表現に文字列リテラルを使うことができる。
"ダブルクオート"と'シングルクオート'
ES2015で追加されたテンプレートリテラル(template literal)を使っても文字列をリテラルで表すことができる。
\`バッククオート\`
エスケープ
code:javascript
const dialog1 = "He looked up and said \"don't do that!\" to Max.";
const dialog2 = 'He looked up and said "don\'t do that!" to Max.';
console.log(dialog1===dialog2); // true
// テンプレートリテラルを使った表現
const dialog3 = He looked up and said "don't do that!" to Max.;
console.log(dialog2===dialog3); // true
エスケープ自身をエスケープしたいときは\\
文字列のクオートはどっちがいいか
": ユーザーに表示する文字列(don'tなどの短縮形を使うことが多い)
': JavaScript文字列内でHTMLを記述する場合(属性値を"で囲める)
特殊文字
\は特殊文字を表すのにも使われる。
\n: 改行
\r: キャリッジリターン
\t: タブ
\': シングルクオート
\\`: バッククオート
\$: ドル記号
\\: バックスラッシュ
\uXXXX: 任意のUnicodeのコードポイント(XXXXは16進数のコードポイント)
\xXX: Latin-1の文字(XXは16進数のLatin-1コードポイント)
テンプレートリテラル
テンプレートリテラルでは$が特別な文字として扱われる。
${...}の中に変数を入れたり演算をしたり関数を呼び出すことができる。
code:javascript
let currentTemp = 19.5;
const message1 = "現在の温度は" + currentTemp + "度です。";
console.log(message1); // 現在の温度は19.5度です。
// テンプレートリテラルを使った表現
const message2 = 現在の温度は${currentTemp}度です。;
console.log(message2); // 現在の温度は19.5度です。
// 演算
console.log(1 + 1 = ${1+1}); // 1 + 1 = 2
複数行にわたる文字列
改行をエスケープすることで複数行を書ける。
code:javascript
// 改行をエスケープするが文字列に改行は含まれない
const multiline = "1行目\
2行目";
console.log(multiline); // 1行目2行目
文字列も改行する場合は改行文字も含める。
code:javascript
const multiline = "1行目 \n\
2行目";
console.log(multiline);
/* 実行結果
1行目
2行目
*/
テンプレートリテラルはより直感的だがインデントも含まれるので注意。
code:javascript
const multiline1 = `1行目
2行目`;
console.log(multiline1);
/* 実行結果
1行目
2行目
*/
// インデントも含まてしまう。
const multiline2 = `1行目
2行目
3行目`;
console.log(multiline2);
/* 実行結果
1行目
2行目
3行目
*/
複数行に分ける必要があるときは文字列の連結などを使うと安全。
文字列としての数値
数を含む文字列はインタプリタが必要に応じて数値に自動変換する。変換ルールは後述。
code:javascript
console.log(3 + '30'); // 330
console.log(3 * '30'); // 90
論理値
論理値リテラル: trueと false
シンボル
ES2015から追加。ほかの識別子と混同しないよう、ユニークな識別子を使いたい場合に利用できる。(プロパティの衝突回避など)
作成したシンボルはユニークになる点でオブジェクトと似ているが、シンボルはプリミティブでリテラルによる表現を持たない。
Symbol()コンストラクタを使って作成する。 newでは作成できない。
code:javascript
const RED = Symbol();
const BLUE = Symbol();
console.log(RED); // Symbol()
console.log(RED === BLUE); // false
const ORANGE = Symbol("夕日の色");
console.log(ORANGE); // Symbol(夕日の色);
nullとundefined
存在しないものを表す。
null: 開発者が変数などの値として利用できるデータ型
undefined: まだ定義されていないもの。
undefinedを意図的も使ってもいいが注意が必要。
オブジェクト
オブジェクトは複数の値や複雑な値を入れることができ、処理の進行に伴って値も変化することができる。
内容が変わっても同じオブジェクト
{...} オブジェクトのリテラル表現
プロパティ(property, もしくはメンバー): 名前と値からなる
プロパティへのアクセス方法
.: メンバーアクセス演算子。
["hoge"]: 計算値によるメンバーアクセス演算子。有効な識別子を使っていないときなど。
code:javascript
const obj = {};
obj.color = "黄色";
console.log(obj.color === obj"color"; // true // ブラケットによるアクセスは文字列リテラルを渡さないとエラー
console.log(objcolor); // ReferenceError: color is not defined. プロパティがシンボルの場合はデフォルトではconsole.log(obj)で表示されない
code:javascript
const obj = {};
const SIZE = Symbol();
console.log(objSIZE); // 8 // シンボルのプロパティはデフォルトでは表示されない
console.log(obj)l // {}
obj.SIZE = 12; // シンボルとは無関係。
console.log(obj.SIZE); // 12
console.log(obj"SIZE"; // 12(上と同じプロパティ) console.log(objSIZE); // 8 console.log(obj); // { SIZE: 12 } (シンボルではなくSIZEプロパティ)
プリミティブとオブジェクトのおさらい
オブジェクトに対する操作を行ってきたが、objはずっと同じオブジェクトを指している。
objに代入されたのがプリミティブであればobjは別の値になっていた。
constでobjを宣言したのでobjは定数だが、objの中身(プロパティの値)を変化させてもエラーにはならない
リテラル表記を使ってプロパティの値を指定しつつオブジェクトを生成することもできる。
複数設定する場合はカンマで区切る。
プロパティの値にオブジェクトを指定することもできる。
オブジェクトはプロパティとして関数(function)をもつこともできる。プロパティで使われる関数はメソッドと呼ばれる。
数値、文字列、論理値に対応するオブジェクト
数値、文字列、論理値には対応するオブジェクト型(Number, String, Boolean)がある。
目的
特殊な値(Number.INFINITYなど)をプロパティとして記憶して使えるようにする
メソッドの形で様々な機能を提供すること
code:javascript
const s = "hello";
const s2 = s.toUpperCase();
console.log(s2); // HELLO
sは一見オブジェクトのように見えるが、文字列型(プリミティブ)のはず。
関数toUpperCaseをプロパティとして持っているStringオブジェクトを一時的に生成している。
このオブジェクトは関数が呼び出されるとすぐに破棄される。
code:javascript
const s = "hello";
s.rating = 3; // エラーなし
console.log(s.rating); // undefined
文字列sにプロパティを追加しているように見えるが、一時的に作成されたStringオブジェクトにプロパティを追加しているだけなので、すぐに破棄される。
配列
リテラル表現[] 要素間はカンマで区切る
代入する添字が最後の要素の添字よりも大きい場合は配列が大きくなる。(間は空要素になる。lengthの値も増える)
非推奨 配列もオブジェクトなので整数以外のキーも可能 (lengthの値に影響なし)
配列やオブジェクトの最終要素のあとのカンマ
JavaScriptの構文では問題ない
JSONでは最終要素の後のカンマは禁止されている
日時
実用上問題が多い
Javaから直接移植された
正規表現
JavaScriptの正規表現はRegExpというオブジェクトで表される
/.../ リテラル表現
マップ(Map)とセット(Set)
ES2015から追加
Mapはオブジェクトと同様にキーと値が対応しているもの
Setは配列と似ているが重複を含めることができない
データの型変換
数値への変換
Numberオブジェクトのコンストラクタを使う方法
code:javascript
const numStr = "33.3";
const num = Number(numStr);
console.log(num); // 33.3
組み込み関数のparseIntまたはparseFloatを使う方法
parseIntでは基数を指定できる。10進数がデフォルトで省略可能だが指定したほうがよい。
どちらも数字以外の情報をすべて無視する
code:javascript
const a = parseInt("16 volts", 10);
console.log(a); // 16
const b = parseInt("3a", 16); // 3a は16進数として解釈
console.log(b); // 58
const c = parseFloat("15.5 kph"); // parseFloatは常に10進数として解釈
console.log(c); // 15.5
論理値に1, 0を振るのに条件演算子を使う場合
code:javascript
const b = true;
const c = false;
const n = b ? 1 : 0;
console.log(n); // 1
const m = c ? 1 : 0;
console.log(m); // 0
文字列への変換
toStringメソッドはJavaScriptのすべてのオブジェクトで使えるがあまり出番がない
ほとんどのオブジェクトは[object Object]が返ってくるだけ(文字列表現をいじることはできる)
Dateオブジェクトと配列では役に立つ。
code:javascript
const d = new Date();
console.log(d.toString()); // 'Sun Oct 28 2018 16:39:04 GMT+0900 (JST)'
console.log(arr); // 1,true,hello
論理値への変換
すべての値は「真とみなされる(truthy)値」か「偽とみなされる(falsy)値」にわけられる(詳しくは後述)
NOT演算子!を2回使えばどの値も論理値に変換できる。
数値変換はBooleanコンストラクタを使う方法もある。
code:javascript
const n = 0;
const b0 = !n;
const b1 = !!n;
const b2 = Boolean(n);
console.log(n); // 0
console.log(b0); // true
console.log(b1); // false
console.log(b2); // false